home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
The World of Computer Software.iso
/
pdclk145.zip
/
PING.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-10-03
|
17KB
|
780 lines
; ping.asm
;========================================================================
; Copyright (C) 1991 by Jan.Engvald@ldc.lu.se, see file COPYING.
MsgEchoHead db CR, LF, "Ping with packet size "
MsgEchoSweep db " "
MsgEchoSize db "0 and interval"
MsgEchoMs db " 0 ms to "
MsgEchoTarget db "1.2.3.4 :", CR, LF, LF
MsgEchoStats db "───────── Packets ──────── ║ ────── Delay ms ────── ║ Packet ║ Load ║ Time ", CR, LF
db "transmit receive diff ║ this min avg max ║ loss ║ kb/s ║ s ", CR, LF, "$$"
MsgEcho db " 0 0 0 0 0 0 0 0.0000 % 0 0 ", CR, '$'
MsgSerrTbl dw offset MsgSerrUnr
dw offset MsgSerrObuf
dw offset MsgSerrNoarp
dw offset MsgSerrTimout
dw offset MsgSerrNotraf
SERRTABLEN equ $-MsgSerrTbl
dw offset MsgSerrUnimpl
MsgSerrUnr db LF, "Host or net unreachable", CR, LF, '$'
MsgSerrObuf db LF, "Temporary out of buffers", CR, LF, '$'
MsgSerrNoarp db LF, "Got no ARP reply", CR, LF, '$'
MsgSerrTimout db LF, "Timeout", CR, LF, '$'
MsgSerrNotraf db LF, "Received no traffic from destination", CR, LF, '$'
MsgSerrUnimpl db LF, "Send Error.", CR, LF, '$'
even
EchoTarget dw 0, 0 ; echo argument values
EchoSize dw 32
EchoInterval dw 256
EchoData dw 101h
EchoDataIncW dw 1
EchoStart dw 0, 0, 0 ; echo variables
EchoNext dw 0
EchoLastDispl dw 0
EchoLastHi dw 0
EchoMaxSize dw 1500
EchoAvgSum dw 0, 0
EchoFudge dw 0
EchoLoad dw 0, 0
EchoPrevLoad dw 0, 0
EchoDrop dw 0
EchoLastErr dw 0
PingRowCnt dw 17
k55 dw 55
k100 dw 100
k220 dw 220
EchoTx32 dw 0, 0 ; echo display variables
EchoRx32 dw 0, 0
EchoDif dw 0, 0
EchoThis dw 0
EchoMin dw 0ffffh
EchoAvg dw 0
EchoMax dw 0
EchoLoss dw 0, 0
EchoElapsed dw 0, 0
;************************************************************************
;* EchoAwhile
;************************************************************************
MsgCalling db "Calling nameserver(s)... $"
MsgNameRep db "got reply in "
MsgNameRepTim db " ms.", CR, LF, '$'
MsgBadName db LF, "Bad hostname (or no nameserver).$"
EchoAwhile proc near
cmp EchoTarget,0 ; want to ping someone?
jne EchoYes
ret
EchoYes:
call InitTimer ; prepare millisecond timing
call HardwareTicks
mov EchoStart,si ; note start ticks
mov EchoStart+2,dx
mov EchoStart+4,ax
call DblShrX
mov EchoNext,ax
cmp EchoTarget,127 ; dns lookup to do?
jne EchoIpAddr
mov dx,offset MsgCalling
mov ah,9
int 21h
mov dx,2345h ; ping udp src port
xor ax,ax ; NsId
mov si,offset EchoNameBuf ; Ns question string
call NsResolve ; call nameserver(s)
call HardwareTicks ; response time
sub ax,EchoStart+4
sbb dx,EchoStart+2
div kTimerScale
mov di,offset MsgNameRepTim
mov PutNumFiller,' '
mov PutMinDigits,4
call PutNum
mov dx,offset MsgNameRep ; display it.
mov ah,9
int 21h
cmp EchoTarget,127 ; name resolved?
jne EchoIpAddr
mov dx,offset MsgBadName
mov ah,9
int 21h
EchoErrTerm:
mov al,'e'-'0'
call terminate
EchoIpAddr:
test ArgFlags,MAKE_TABLE
jz EchoNotTbl
or GenFlags,TBL_READY
EchoNotTbl:
mov di,offset EchoSizeVec
mov cx,(EchoSizeEnd-EchoSizeVec)/2
xor ax,ax
rep stosw
test ArgFlags,TERM_WAIT
jnz EchoAsIs
cmp EchoInterval,128
jge EchoAsIs
mov EchoInterval,128
EchoAsIs:
call BufAlloc ; get a send buf
jz EchoErrTerm
call MakeSendDescr
mov [di].uIcmpTypeCode,8 ; type = echo request
test GenFlags,UDP_ECHO
jz EchoUseIcmp
mov word ptr MsgEchoHead+2,'cE'
mov word ptr MsgEchoHead+4,'oh'
mov word ptr [di].uUdpSrc,0703h ; my udp echo port
mov word ptr [di].uUdpDst,0900h ; dst discard port
test ArgFlags,UDP_DISCARD
jnz EchoUseIcmp
mov word ptr [di].uUdpDst,0700h ; dst echo port
EchoUseIcmp:
mov cx,(1500-IPHDRLEN-ICMPHDRLEN-4)/2
add di,ICMPHDRLEN+4
mov ax,EchoData
EchoFillLoop:
stosw
add ax,EchoDataIncW
loop EchoFillLoop
EchoFillEnd:
mov si,offset EchoTarget-iIpSrc
call SwitchIpdstB ; set IP destination
mov si,offset EchoTarget
mov di,offset MsgEchoTarget
call PutIpNum ; tell who we are pinging
mov cx,EchoSize
or cx,cx
jns EchoSizePos
neg cx
mov MsgEchoSweep,'<'
EchoSizePos:
sub cx,IPHDRLEN+ICMPHDRLEN+4
cmp cx,GIANT-HWHDRLEN-IPHDRLEN-ICMPHDRLEN-4
jbe EchoOkSize
xor cx,cx
EchoOkSize:
mov ax,cx
add ax,IPHDRLEN+ICMPHDRLEN+4
mov EchoSize,cx
mov EchoMaxSize,cx
mov di,offset MsgEchoSize
mov PutMinDigits,1
call PutNum ; and the packet size used
mov ax,EchoInterval
mov di,offset MsgEchoMs
mov PutMinDigits,6
mov PutNumFiller,' '
call PutNum ; and interval in ms
mov dx,offset MsgEchoHead
mov ah,9
int 21h ; display it
EchoLoop0:
nop ; (just to separate the loops)
EchoLoop:
call Something2Do ; process other things
jnz EchoLoop ; maybe more to do
call EchoDisplay ; show current values
call AnyKey ; first key stops sending
jz EchoNoKey
if 0
cmp al,'y' and 01fh ; ignore most control keys
jbe EchoNoKey
endif
jmp EchoEnd
EchoNoKey:
cmp FreeBufs.lBufsAvail,3*NBUFS/4
jle EchoLoop ; prevent buffer starving
call HardwareTicks
call DblShrX
mov dx,ax
sub ax,EchoNext ; time to send next echo pkt?
js EchoLoop0
add dx,EchoInterval
mov EchoNext,dx ; next send time
add EchoTx32+2,1 ; increment send counters
adc EchoTx32,0
mov EchoFudge,1
mov cx,EchoSize ; compute packet size
cmp MsgEchoSweep,'<'
jne EchoFillFixed
inc cx
cmp cx,EchoMaxSize
jbe EchoFillSize
mov cx,28-IPHDRLEN-ICMPHDRLEN
EchoFillSize:
mov EchoSize,cx
EchoFillFixed:
add cx,ICMPHDRLEN+4 ; IP data length
mov di,cx
shl di,1
inc word ptr EchoSizeVec[di]
call HardwareTicks ; put timestamp
mov di,[bx].dPtrUdp
mov [di].uUdpData,ax
mov [di].uUdpData+2,dx
test GenFlags,UDP_ECHO
jnz EchoUdp
call SendIcmpPkt ; send icmp echo pkt
EchoLoop8:
jnz EchoErr ; any errors?
EchoLoop9:
mov EchoLastErr,cx
jmp EchoLoop
EchoUdp:
mov ax,cx
call SendUdpPkt ; send udp echo pkt
jmp short EchoLoop8
EchoErr:
cmp cx,EchoLastErr
je EchoLoop9
push cx
xor ch,ch
cmp cl,SERRTABLEN
jb EchoErrExist
mov cl,SERRTABLEN
EchoErrExist:
mov si,cx
mov dx,MsgSerrTbl[si]
mov ah,9
int 21h ; display send error
pop cx
test ArgFlags,TERM_WAIT
jnz EchoLoop9
EchoEnd:
call BufRelease ; release send buffer
mov EchoFudge,0
or ArgFlags,TERM_WAIT
ret
EchoAwhile endp
if DEBUG
TstBufLinks proc near
ja TstErrEI
mov si,di
inc cx
TstLinkLoop:
mov di,[di].dNext
mov si,[si].dPrev
loop TstLinkLoop
cmp si,di
jne TstErrEI
ret
TstBufLinks endp
TstErrEI:
PopfEI
TstErr:
push bx
mov bx,'>-'
push bx
push bx
call terminate
endif ; DEBUG
;************************************************************************
;* EchoDisplay
;************************************************************************
EchoDisplay proc near
if DEBUG
push bx
mov al,'s'-'0'
cmp word ptr phd_dioa,0 ; stack overflowed?
jne TstErr
mov al,'t'-'0'
cmp word ptr StackLow,0 ; stack overflowed?
jne TstErr
mov al,'i'-'0'
test GenFlags,DBGINTERR ; any interrupt debug errs?
jnz TstErr
mov cx,NBUFS ; any buffers damaged?
mov bx,offset BufStart
mov al,'u'-'0'
BufTestLoop:
cmp [bx].dHomeList,offset FreeBufs
jne TstErr
add bx,BUFSIZE
loop BufTestLoop
PushfDI
mov di,offset FreeBufs
mov cx,[di].lBufsAvail
cmp cx,NBUFS
call TstBufLinks
cmp di,offset FreeBufs
jne TstErrEI
PopfEI
mov cx,NBUFSMALL
mov al,'v'-'0'
TstSmlLoop:
cmp [bx].dHomeList,offset FreeSmal
jne TstErr
add bx,BUFSIZESML
loop TstSmlLoop
PushfDI
mov di,offset FreeSmal
mov cx,[di].lBufsAvail
cmp cx,NBUFSMALL
call TstBufLinks
cmp di,offset FreeSmal
jne TstErrEI
PopfEI
pop bx
endif ; DEBUG
; *test cmp EchoTarget,0 ; are we pinging?
; je EchoDispRet
call CurrentTicks
shr cx,1
shr cx,1
mov ax,EchoLastDispl
shr ax,1
shr ax,1
cmp ax,cx ; time to update display?
jne EchoDispNow
EchoDispRet:
ret
EchoDispNow:
push bx
cli
mov dx,EchoAvgSum
mov ax,EchoAvgSum+2
mov cx,EchoRx32
mov bx,EchoRx32+2
sti
call AdjTo16Bits
or bx,bx ; avoid div by zero
jz EchoSkipAvg
div bx
mov EchoAvg,ax ; average delay
EchoSkipAvg:
mov dx,EchoTx32 ; compute difference tx - rx
mov ax,EchoTx32+2
sub ax,EchoFudge ; subtract one if just
sbb dx,0 ; sent a pkt
push ax
push dx
cli
sub ax,EchoRx32+2
sbb dx,EchoRx32
sti
jns EchoDifPos ; use abs(tx-rx)
not ax
not dx
add ax,1
adc dx,0
EchoDifPos:
mov Echodif,dx
mov Echodif+2,ax
mov cl,2 ; compute packet loss
call DblShl ; multiply by 100
mov si,dx
mov bx,ax
mov cl,3
call DblShl
add bx,ax
adc si,dx
shl ax,1
rcl dx,1
add ax,bx
adc dx,si
pop cx
pop bx
call AdjTo16Bits
or bx,bx ; avoid div by zero
jz EchoSkipLoss
div bx
mov EchoLoss,ax
mov ax,dx ; fractional loss
mul k10000
div bx
mov EchoLoss+2,ax
EchoSkipLoss:
push cs ; edit echo values
pop es
mov di,offset MsgEcho-1
mov si,offset EchoTx32
mov PutNumFiller,' '
mov PutMinDigits,9
mov cx,3
call PutBigNums ; tx and rx and diff
mov PutMinDigits,6
inc di
mov cx,5
EchoDispLoop:
push cx
mov cl,1
call PutNums ; delays and loss
pop cx
loop EchoDispLoop
mov PutNumFiller,'0'
inc di
mov cl,1
call PutNumsD4 ; .0000%
cli
mov ax,EchoLoad+2
mov bx,ax
mov dx,EchoLoad
mov cx,dx
add ax,EchoPrevLoad+2
adc dx,EchoPrevLoad
mov EchoLoad+2,0
mov EchoLoad,0
sti
mov EchoPrevLoad+2,bx
mov EchoPrevLoad,cx
div k55 ; assumes clr every 2nd tick
add di,4
mov PutNumFiller,' '
call PutNum ; load kb/s
call HardwareTicks ; compute elapsed time
mov ax,dx
mov dx,si
cmp dx,EchoLastHi
jae EchoLastGrows
mov bx,EchoLastDispl
mov cx,EchoLastHi
sub EchoStart+2,bx
sbb EchoStart,cx
EchoLastGrows:
mov EchoLastDispl,ax
mov EchoLastHi,dx
sub ax,EchoStart+2
sbb dx,EchoStart
mov cl,4 ; divide # of ticks by 18.2
call DblShr
mov EchoElapsed+2,ax
mov EchoElapsed,dx
mov cl,3
call DblShr
sub EchoElapsed+2,ax
sbb EchoElapsed,dx
mov cl,5
call DblShr
add ax,EchoElapsed+2
adc dx,EchoElapsed
mov PutNumFiller,' '
mov PutMinDigits,8
call PutBigNum ; elapsed time
if DEBUG
mov dx,280h+10h ; assume WD card at IO 280h
xor ax,ax
xor cx,cx
cli
out dx,al ; set page 0
call IoDelay
add dx,0dh
in al,dx ; readandclear frame err ctr
add cx,ax
inc dx
in al,dx ; readnadclear bad CRC ctr
add cx,ax
inc dx
in al,dx ; readandclear lost frames ctr
sti
add cx,ax
add EchoDrop,cx ; add out of bufs ctr
endif ; DEBUG
mov ax,EchoDrop
if DEBUG eq 0
or ax,ax
jz EchoNoDrops
endif ; DEBUG eq 0
mov di,offset MsgEcho+18 ; place before diff
mov PutMinDigits,1
call PutNum ; show dropped packets
EchoNoDrops:
mov dx,offset MsgEcho ; display echo values
mov ah,9
int 21h
pop bx
ret
EchoDisplay endp
;************************************************************************
;* AdjTo16Bits
;************************************************************************
AdjTo16Bits proc near
AdjTest:
or cx,cx ; fits in 16 bits?
jnz Adjust
or dx,dx
jnz Adjust
ret
Adjust:
shr dx,1 ; shift 32 bits right
rcr ax,1
shr cx,1
rcr bx,1
jmp short AdjTest
AdjTo16Bits endp
;************************************************************************
;* DblShrX
;************************************************************************
DblShrX proc near
mov cx,7
test ArgFlags,MICRO_100
jnz DblShr
DblShr10:
mov cl,10
DblShr:
xor ch,ch
DblShrNext:
shr dx,1 ; shift 32 bits right
rcr ax,1
loop DblShrNext
ret
DblShrX endp
;************************************************************************
;* DblShl
;************************************************************************
DblShl proc near
xor ch,ch
DblShlNext:
shl ax,1 ; shift 32 bits left
rcl dx,1
loop DblShlNext
ret
DblShl endp
;************************************************************************
;* EchoCalc
;************************************************************************
even
kTimerScale dw TimerResolution
EchoCalc proc near
add EchoRx32+2,1 ; increment receive counters
adc EchoRx32,0
mov EchoFudge,0
mov di,[bx].dPktLen ; IP data length
shl di,1
dec word ptr EchoSizeVec[di]
call HardwareTicks ; compute delay
mov di,[bx].dPtrUdp
sub ax,[di].uUdpData
sbb dx,[di].uUdpData+2
js EchoCalcRet
div kTimerScale
mov EchoThis,ax ; delay for this packet
add EchoAvgSum+2,ax
adc EchoAvgSum,0
cmp ax,EchoMin
jb EchoSetMin
EchoChkMax:
cmp ax,EchoMax
ja EchoSetMax
EchoCalcRet:
ret
EchoSetMin:
mov EchoMin,ax ; minimum delay
jmp short EchoChkMax
EchoSetMax:
mov EchoMax,ax ; maximum delay
ret
EchoCalc endp
;************************************************************************
;* HardwareTicks (48 bit time to si:dx:ax in 838 ns units)
;************************************************************************
TimerResolution equ 1193 ; hw ticks per millisecond
InitTimer proc near
test ArgFlags,TIM_NOHIRES
jnz InitTimRet
mov dx,043h ; select timer control port
mov al,034h
out dx,al ; mode 2: Rate generator
call IoDelay ; (counts down by 1 to zero)
xor ax,ax
mov dx,040h ; select timer 0
out dx,al ; set divide by 2**16
call IoDelay
out dx,al ; the generator is now started
InitTimRet:
ret
InitTimer endp
RestoreTimer proc near
test ArgFlags,TIM_NOHIRES
jnz ResTimRet
mov dx,043h ; select timer control port
mov al,036h
out dx,al ; mode 3: Square wave generator
call IoDelay ; (counts down by 2 to zero,
xor ax,ax ; twice)
mov dx,040h ; select timer 0
out dx,al ; set divide by 2**16
call IoDelay
out dx,al
ResTimRet:
ret
RestoreTimer endp
IoDelay proc near
push ax
in al,061h
pop ax
ret
IoDelay endp
HardwareTicks proc near
push es
PushfDI
test ArgFlags,TIM_NOHIRES
jnz HwTicksNoHi
mov dx,020h ;/* Address PIC ocw3 */
mov al,00Ah ;/* Ask to read irr */
out dx,al
xor al,al ;/* Latch timer 0 */
out 043h,al
in al,040h ;/* Counter --> ax*/
mov ah,al ;/* LSB in AH */
in al,040h ;/* MSB in AL */
xchg al,ah
not ax ;/* Need ascending counter */
push ax ; Save hardware counter value
in al,dx ;/* Read irr */
push ax ; Save irr
in al,021h ;/* Read PIC imr */
push ax ; Save imr
mov al,00FFh ;/* Mask all interrupts */
out 021h,al
mov ax,040h ;/* read low word of time */
mov es,ax ;/* from BIOS data area */
mov dx,es:[06Ch]
mov si,es:[06Ch+2] ; get high word too
pop ax ; Restore imr
out 021h,al
pop ax ; Restore irr
test al,001h ;/* Counter hit 0? */
pop ax ; Restore counter value
jnz HwTicksMore ;/* Jump if yes */
popfEI
pop es
ret
HwTicksMore:
cmp ax,0FFh ;/* Counter > 0x0FF? */
ja HwTicksDone ;/* Done if so */
inc dx ;/* Else count int req. */
HwTicksDone:
popfEI
pop es
ret
HwTicksNoHi:
mov ax,040h ;/* read low word of time */
mov es,ax ;/* from BIOS data area */
mov dx,es:[06Ch]
mov si,es:[06Ch+2]
xor ax,ax
popfEI
pop es
ret
HardwareTicks endp
;========================================================================
; endinclude